Türkçe

Next.js middleware'ini kullanarak gelişmiş istek değiştirme tekniklerini keşfedin. Güçlü web uygulamaları için karmaşık yönlendirme, kimlik doğrulama, A/B testi ve yerelleştirme stratejilerini öğrenin.

Next.js Middleware Kenar Durumları: İstek Değiştirme Desenlerinde Ustalık

Next.js middleware, isteklerin uygulamanızın rotalarına ulaşmadan önce yakalanması ve değiştirilmesi için güçlü bir mekanizma sağlar. Bu yetenek, basit kimlik doğrulama kontrollerinden karmaşık A/B testi senaryolarına ve uluslararasılaştırma stratejilerine kadar geniş bir olasılık yelpazesi açar. Ancak, middleware'den etkili bir şekilde yararlanmak, onun kenar durumlarını ve potansiyel tuzaklarını derinlemesine anlamayı gerektirir. Bu kapsamlı kılavuz, gelişmiş istek değiştirme desenlerini araştırır, sağlam ve performanslı Next.js uygulamaları oluşturmanıza yardımcı olmak için pratik örnekler ve uygulanabilir içgörüler sağlar.

Next.js Middleware'in Temellerini Anlamak

Gelişmiş desenlere dalmadan önce, Next.js middleware'in temellerini özetleyelim. Middleware fonksiyonları, bir istek tamamlanmadan önce yürütülür ve şunları yapmanızı sağlar:

Middleware fonksiyonları, /pages veya /app dizininizde (Next.js sürümünüze ve kurulumunuza bağlı olarak) middleware.js veya middleware.ts dosyasında bulunur. Gelen isteği temsil eden bir NextRequest nesnesi alırlar ve sonraki davranışı kontrol etmek için bir NextResponse nesnesi döndürebilirler.

Örnek: Temel Kimlik Doğrulama Middleware'i

Bu örnek, basit bir kimlik doğrulama kontrolü göstermektedir. Kullanıcı kimliği doğrulanmamışsa (örneğin, bir çerezde geçerli bir belirteç yoksa), oturum açma sayfasına yönlendirilir.


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const authToken = request.cookies.get('authToken')

  if (!authToken) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/protected/:path*'],
}

Bu middleware yalnızca /protected/:path* ile eşleşen rotalar için çalışacaktır. Bir authToken çerezinin varlığını kontrol eder. Çerez eksikse, kullanıcı /login sayfasına yönlendirilir. Aksi takdirde, istek NextResponse.next() kullanılarak normal şekilde devam etmesine izin verilir.

Gelişmiş İstek Değiştirme Desenleri

Şimdi, Next.js middleware'in gerçek gücünü sergileyen bazı gelişmiş istek değiştirme desenlerini keşfedelim.

1. Çerezlerle A/B Testi

A/B testi, kullanıcı deneyimlerini optimize etmek için çok önemli bir tekniktir. Middleware, kullanıcıları uygulamanızın farklı varyasyonlarına rastgele atamak ve davranışlarını izlemek için kullanılabilir. Bu desen, kullanıcının atanmış varyantını korumak için çerezlere dayanır.

Örnek: Bir Açılış Sayfasını A/B Testi Yapmak


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const VARIANT_A = 'variantA'
const VARIANT_B = 'variantB'

export function middleware(request: NextRequest) {
  let variant = request.cookies.get('variant')?.value

  if (!variant) {
    // Bir varyantı rastgele atayın
    variant = Math.random() < 0.5 ? VARIANT_A : VARIANT_B
    const response = NextResponse.next()
    response.cookies.set('variant', variant)
    return response
  }

  if (variant === VARIANT_A) {
    return NextResponse.rewrite(new URL('/variant-a', request.url))
  } else if (variant === VARIANT_B) {
    return NextResponse.rewrite(new URL('/variant-b', request.url))
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/'],
}

Bu örnekte, bir kullanıcı ilk kez kök yolu (/) ziyaret ettiğinde, middleware onları rastgele variantA veya variantB'ye atar. Bu varyant bir çerezde saklanır. Aynı kullanıcının sonraki istekleri, atanmış varyantlarına bağlı olarak ya /variant-a ya da /variant-b'ye yeniden yazılacaktır. Bu, farklı açılış sayfaları sunmanıza ve hangisinin daha iyi performans gösterdiğini izlemenize olanak tanır. Next.js uygulamanızda /variant-a ve /variant-b için rotalar tanımladığınızdan emin olun.

Küresel Hususlar: A/B testi yaparken, bölgesel varyasyonları göz önünde bulundurun. Kuzey Amerika'da yankı uyandıran bir tasarım, Asya'da aynı derecede etkili olmayabilir. A/B testini belirli bölgelere uyarlamak için coğrafi konum verilerini (IP adresi araması veya kullanıcı tercihleri aracılığıyla elde edilen) kullanabilirsiniz.

2. URL Yeniden Yazma ile Yerelleştirme (i18n)

Uluslararasılaştırma (i18n), küresel bir kitleye ulaşmak için gereklidir. Middleware, kullanıcının tercih ettiği dili otomatik olarak algılamak ve onları sitenizin uygun yerelleştirilmiş sürümüne yönlendirmek için kullanılabilir.

Örnek: Accept-Language Başlığına Göre Yönlendirme


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const SUPPORTED_LANGUAGES = ['en', 'fr', 'es', 'de']
const DEFAULT_LANGUAGE = 'en'

function getPreferredLanguage(request: NextRequest): string {
  const acceptLanguage = request.headers.get('accept-language')
  if (!acceptLanguage) {
    return DEFAULT_LANGUAGE
  }

  const languages = acceptLanguage.split(',').map((lang) => lang.split(';')[0].trim())

  for (const lang of languages) {
    if (SUPPORTED_LANGUAGES.includes(lang)) {
      return lang
    }
  }

  return DEFAULT_LANGUAGE
}

export function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname

  // Pathname'de mevcut bir yerel ayar olup olmadığını kontrol edin
  if (
    SUPPORTED_LANGUAGES.some(
      (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
    )
  ) {
    return NextResponse.next()
  }

  const preferredLanguage = getPreferredLanguage(request)

  return NextResponse.redirect(
    new URL(`/${preferredLanguage}${pathname}`, request.url)
  )
}

export const config = {
  matcher: [
    '/((?!api|_next/static|_next/image|favicon.ico).*)'
  ],
}

Bu middleware, istekten Accept-Language başlığını çıkarır ve kullanıcının tercih ettiği dili belirler. URL zaten bir dil öneki (örneğin, /en/about) içermiyorsa, middleware kullanıcıyı uygun yerelleştirilmiş URL'ye (örneğin, Fransızca için /fr/about) yönlendirir. Farklı yerel ayarlar için `/pages` veya `/app` dizininizde uygun klasör yapısına sahip olduğunuzdan emin olun. Örneğin, bir `/pages/en/about.js` ve bir `/pages/fr/about.js` dosyasına ihtiyacınız olacaktır.

Küresel Hususlar: i18n uygulamanızın sağdan-sola dillere (örneğin, Arapça, İbranice) doğru şekilde işlem yaptığından emin olun. Ayrıca, performansı artırarak, yerelleştirilmiş varlıkları kullanıcılarınıza daha yakın sunuculardan sunmak için bir İçerik Dağıtım Ağı (CDN) kullanmayı düşünün.

3. Özellik Bayrakları

Özellik bayrakları, yeni kod dağıtmadan uygulamanızdaki özellikleri etkinleştirmenize veya devre dışı bırakmanıza olanak tanır. Bu, yeni özellikleri kademeli olarak kullanıma almak veya üretimde özellikleri test etmek için özellikle kullanışlıdır. Middleware, bir özellik bayrağının durumunu kontrol etmek ve isteği buna göre değiştirmek için kullanılabilir.

Örnek: Bir Beta Özelliğini Etkinleştirme


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const BETA_FEATURE_ENABLED = process.env.BETA_FEATURE_ENABLED === 'true'

export function middleware(request: NextRequest) {
  if (BETA_FEATURE_ENABLED && request.nextUrl.pathname.startsWith('/new-feature')) {
    return NextResponse.next()
  }

  // İsteğe bağlı olarak bir "özellik kullanılamıyor" sayfasına yönlendirin
  return NextResponse.rewrite(new URL('/feature-unavailable', request.url))
}

export const config = {
  matcher: ['/new-feature/:path*'],
}

Bu middleware, BETA_FEATURE_ENABLED ortam değişkeninin değerini kontrol eder. true olarak ayarlanmışsa ve kullanıcı /new-feature altında bir rotaya erişmeye çalışıyorsa, isteğin devam etmesine izin verilir. Aksi takdirde, kullanıcı bir /feature-unavailable sayfasına yönlendirilir. Farklı ortamlar (geliştirme, hazırlık, üretim) için ortam değişkenlerini uygun şekilde yapılandırmayı unutmayın.

Küresel Hususlar: Özellik bayrakları kullanırken, tüm bölgelerdeki düzenlemelere uymayan özellikleri etkinleştirmenin yasal sonuçlarını göz önünde bulundurun. Örneğin, veri gizliliği ile ilgili özelliklerin bazı ülkelerde devre dışı bırakılması gerekebilir.

4. Cihaz Algılama ve Uyarlanabilir Yönlendirme

Modern web uygulamalarının duyarlı olması ve farklı ekran boyutlarına ve cihaz yeteneklerine uyum sağlaması gerekir. Middleware, kullanıcının cihaz türünü algılamak ve onları sitenizin optimize edilmiş sürümlerine yönlendirmek için kullanılabilir.

Örnek: Mobil Kullanıcıları Mobil Optimize Edilmiş Bir Alt Alana Yönlendirme


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { device } from 'detection'

export function middleware(request: NextRequest) {
  const userAgent = request.headers.get('user-agent')

  if (userAgent) {
    const deviceType = device(userAgent)

    if (deviceType.type === 'phone') {
      const mobileUrl = new URL(request.url)
      mobileUrl.hostname = 'm.example.com'
      return NextResponse.redirect(mobileUrl)
    }
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/'],
}

Bu örnek, kullanıcının cihaz türünü User-Agent başlığına göre belirlemek için detection kitaplığını kullanır. Kullanıcı bir cep telefonundaysa, m.example.com alt alan adına yönlendirilir (burada sitenizin mobil optimize edilmiş bir sürümünün barındırıldığını varsayarak). detection paketini yüklemeyi unutmayın: npm install detection.

Küresel Hususlar: Cihaz algılama mantığınızın, cihaz kullanımındaki bölgesel farklılıkları hesaba kattığından emin olun. Örneğin, bazı gelişmekte olan ülkelerde özellikli telefonlar hala yaygındır. Daha sağlam bir çözüm için Kullanıcı-Aracı algılama ve duyarlı tasarım tekniklerinin bir kombinasyonunu kullanmayı düşünün.

5. İstek Başlığı Zenginleştirme

Middleware, uygulamanızın rotaları tarafından işlenmeden önce istek başlıklarına bilgi ekleyebilir. Bu, uygulama mantığınız tarafından kullanılabilecek özel meta veriler (kullanıcı rolleri, kimlik doğrulama durumu veya istek kimlikleri gibi) eklemek için kullanışlıdır.

Örnek: Bir İstek Kimliği Ekleme


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { v4 as uuidv4 } from 'uuid'

export function middleware(request: NextRequest) {
  const requestId = uuidv4()
  const response = NextResponse.next()
  response.headers.set('x-request-id', requestId)
  return response
}

export const config = {
  matcher: ['/api/:path*'], // Yalnızca API rotalarına uygulayın
}

Bu middleware, uuid kitaplığını kullanarak benzersiz bir istek kimliği oluşturur ve bunu x-request-id başlığına ekler. Bu kimlik daha sonra günlüğe kaydetme, izleme ve hata ayıklama amaçları için kullanılabilir. uuid paketini yüklemeyi unutmayın: npm install uuid.

Küresel Hususlar: Özel başlıklar eklerken, başlık boyutu sınırlarına dikkat edin. Bu sınırların aşılması beklenmeyen hatalara yol açabilir. Ayrıca, başlıklarına eklenen hassas bilgilerin (özellikle uygulamanız bir ters vekil sunucu veya CDN'nin arkasındaysa) uygun şekilde korunduğundan emin olun.

6. Güvenlik Geliştirmeleri: Hız Sınırlama

Middleware, belirli bir zaman diliminde bir istemcinin yapabileceği istek sayısını sınırlayarak, kötü niyetli saldırılara karşı ilk savunma hattı olarak görev yapabilir.

Örnek: Basit bir Mağaza Kullanarak Temel Hız Sınırlama


import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const requestCounts: { [ip: string]: number } = {}
const WINDOW_SIZE_MS = 60000; // 1 dakika
const MAX_REQUESTS_PER_WINDOW = 100;

export function middleware(request: NextRequest) {
  const clientIP = request.ip || '127.0.0.1' // İstemci IP'sini alın, yerel test için varsayılan olarak localhost

  if (!requestCounts[clientIP]) {
    requestCounts[clientIP] = 0;
  }

  requestCounts[clientIP]++;

  if (requestCounts[clientIP] > MAX_REQUESTS_PER_WINDOW) {
    return new NextResponse(
      JSON.stringify({ message: 'Çok fazla istek' }),
      {
        status: 429,
        headers: { 'Content-Type': 'application/json' }
      }
    );
  }

  // Pencereden sonra sayacı sıfırla
  setTimeout(() => {
    requestCounts[clientIP]--;
    if (requestCounts[clientIP] <= 0) {
        delete requestCounts[clientIP];
    }
  }, WINDOW_SIZE_MS);

  return NextResponse.next();
}

export const config = {
  matcher: ['/api/:path*'], // Tüm API rotalarına uygula
}

Bu örnek, her IP adresinden gelen istek sayısını izlemek için basit bir bellek içi mağaza (requestCounts) tutar. Bir istemci WINDOW_SIZE_MS içinde MAX_REQUESTS_PER_WINDOW'u aşarsa, middleware bir 429 Çok Fazla İstek hatası döndürür. Önemli: Bu basitleştirilmiş bir örnektir ve ölçeklenmediği ve hizmet reddi saldırılarına karşı savunmasız olduğu için üretim ortamları için uygun değildir. Üretimde kullanım için, Redis veya özel bir hız sınırlama hizmeti gibi daha sağlam bir hız sınırlama çözümü kullanmayı düşünün.

Küresel Hususlar: Hız sınırlama stratejileri, uygulamanızın özel özelliklerine ve kullanıcılarınızın coğrafi dağılımına göre uyarlanmalıdır. Farklı bölgeler veya kullanıcı segmentleri için farklı hız limitleri kullanmayı düşünün.

Kenar Durumları ve Potansiyel Tuzaklar

Middleware güçlü bir araç olmakla birlikte, sınırlamalarının ve potansiyel tuzaklarının farkında olmak çok önemlidir:

Next.js Middleware Kullanımı İçin En İyi Uygulamalar

Next.js middleware'in faydalarını en üst düzeye çıkarmak ve olası sorunlardan kaçınmak için şu en iyi uygulamaları izleyin:

Sonuç

Next.js middleware, istekleri değiştirmek ve uygulamanızın davranışını kenarda özelleştirmek için güçlü bir yol sunar. Bu kılavuzda tartışılan gelişmiş istek değiştirme desenlerini anlayarak, sağlam, performanslı ve küresel olarak farkında olan Next.js uygulamaları oluşturabilirsiniz. Kenar durumlarını ve potansiyel tuzakları dikkatlice değerlendirmeyi ve middleware fonksiyonlarınızın güvenilir ve bakımı kolay olmasını sağlamak için yukarıda özetlenen en iyi uygulamaları izlemeyi unutmayın. Olağanüstü kullanıcı deneyimleri yaratmak ve web uygulamalarınız için yeni olanakların kilidini açmak için middleware'in gücünü kucaklayın.